package socket.myRPC.rpc.transport;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import socket.myRPC.rpc.protocol.MyContent;
import socket.myRPC.rpc.protocol.MyHeader;
import socket.myRPC.util.Define;
import socket.myRPC.util.PackageMsg;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.List;

/**
 * 表示 字节转换 Decoder
 * <p>
 * getBytes()
 * 1. 方法用于从 ByteBuf（字节缓冲区）中将所有可读字节复制到一个新的 byte 数组中，并返回该 byte 数组
 * 2. 方法会将 ByteBuf 中的所有可读字节复制到新的 byte 数组中，不会改变 ByteBuf 的读取位置或状态
 * readBytes()
 * 1. 方法用于从 ByteBuf 中读取指定长度的字节数据，并返回一个新的 ByteBuf 对象，其中包含了读取的字节数据.
 * 2. 方法会移动 ByteBuf 的读取位置，将读取的字节数据存储到新的 ByteBuf 中.
 *
 * @author lihh
 */
public class ServerDecode extends ByteToMessageDecoder {
  
  //父类里一定有 channelRead {  前老的拼buf  decode（）；剩余留存 ;对out遍历 } -> byteBuf
  //因为你偷懒，自己能不能实现！
  @Override
  protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
    int DATA_LENGTH = 122;
    // 1. readableBytes 该api 来获取 可读取的 byte 长度
    // 2. 如果是 >= 的场合, 说明还可以 读取接下来的 byte
    while (byteBuf.readableBytes() >= DATA_LENGTH) {
      // 这里 定义一个指定的字节长度的 byte
      byte[] bytes = new byte[DATA_LENGTH];
      // 拿到 指定byte 的内容
      // 3. readerIndex() 返回的是当前读取位置的索引
      // 4. 从 readerIndex()位置开始读取, 读取的内容 bytes[]
      byteBuf.getBytes(byteBuf.readerIndex(), bytes);
      
      ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(bytes));
      // 读取 对象流 的内容
      MyHeader header = (MyHeader) oin.readObject();
      
      // 如果还有值的话 还可以继续读
      // 5. 是否还可以 读取一次 DATA_LENGTH 的长度
      if (byteBuf.readableBytes() - DATA_LENGTH >= header.getDataLen()) {
        byteBuf.readBytes(DATA_LENGTH);
        
        byte[] data = new byte[(int) header.getDataLen()];
        // 这里 读取内容 && 移动索引
        byteBuf.readBytes(data);
        
        ObjectInputStream doin = new ObjectInputStream(new ByteArrayInputStream(data));
        // 这里分别处理 读以及写  0x14141414 0x14141424
        if (header.getFlag() == Define.REQUEST_FLAG) {
          MyContent content = (MyContent) doin.readObject();
          list.add(new PackageMsg(header, content));
        } else if (header.getFlag() == Define.RESPONSE_FLAG) {
          MyContent content = (MyContent) doin.readObject();
          list.add(new PackageMsg(header, content));
        }
      } else {
        break;
      }
    }
  }
}
